from django import forms
from django.db import models
from modelcluster.fields import ParentalKey, ParentalManyToManyField
from modelcluster.models import ClusterableModel

# Tagging Posts: New imports added for ClusterTaggableManager, TaggedItemBase, MultiFieldPanel
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBase
from taggit.managers import TaggableManager

from wagtail.core import blocks
from wagtail.api import APIField
from wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField, StreamField
from wagtail.images.blocks import ImageChooserBlock
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanel, StreamFieldPanel, FieldRowPanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index
from wagtail.snippets.models import register_snippet        #Categories
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from wagtail.snippets.edit_handlers import SnippetChooserPanel


# Create your models here.

class BlogIndexPage(Page):
    intro = RichTextField(blank=True)

    # 内容分页
    def get_context(self, request):
        # Update context to include only published posts, ordered by reverse-chron
        context = super().get_context(request)
        blogpages = self.get_children().live().order_by('-first_published_at')
        paginator = Paginator(blogpages, 6) # Show 3 resources per page

        page = request.GET.get('page')
        try:
            blogpages = paginator.page(page)
        except PageNotAnInteger:
            # If page is not an integer, deliver first page.
            blogpages = paginator.page(1)
        except EmptyPage:
            # If page is out of range (e.g. 9999), deliver last page of results.
            blogpages = paginator.page(paginator.num_pages)

        # make the variable 'resources' available on the template
        context['blogpages'] = blogpages

        return context

    
    content_panels = Page.content_panels + [
        FieldPanel('intro','简介', classname="full")
    ]

    # Speficies that only BlogPage objects can live under this index page
    subpage_types = ['BlogPage']

    # context_object_name = '快乐星球'


class BlogPageTag(TaggedItemBase):
    print('blog_page_tag，这里有执行吗？')
    content_object = ParentalKey(
        'BlogPage',
        related_name="tagged_items",
        on_delete=models.CASCADE
    )


class BlogPage(Page):
    date = models.DateField("发布日期")
    intro = models.TextField("简介", max_length=100)
    body = RichTextField("内容")
    tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
    # tags_list = BlogPageTag.objects.values('name').first()
    categories = ParentalManyToManyField('blog.BlogCategory', blank=True, verbose_name='内容分类')
    # adverts = ParentalManyToManyField('blog.Advert', blank=True, verbose_name='链接')
    cover = models.ForeignKey('wagtailimages.Image', on_delete=models.DO_NOTHING, related_name='+', verbose_name='封面')
    total_views = models.PositiveIntegerField(default=0)
    
    def increase_views(self):
         self.total_views += 1
         self.save(update_fields=['total_views'])

    search_fields = Page.search_fields + [
        index.SearchField('intro'),
        index.SearchField('body'),
    ]

    content_panels = Page.content_panels + [
        FieldPanel('intro'),
        MultiFieldPanel([
            FieldPanel('tags', classname="col10", help_text='你好吖'),
            #
            FieldRowPanel([
                FieldPanel('date', classname="col4"),
                FieldPanel('categories', widget=forms.ChoiceField(), help_text='请选择分类', classname="col4"),
            ]),

            # FieldPanel('categories', widget=forms.CheckboxSelectMultiple(), help_text='请选择分类'),
            # FieldPanel('adverts', widget=forms.ModelChoiceField),
            ImageChooserPanel('cover'),
            InlinePanel('blog_person_relationship', label='Author(s)', panels=None, min_num=1),
        ], heading="文章信息"),
        FieldPanel('body', classname="full"),
        # StreamFieldPanel('body'),
        
    ]

    # Specifies parent to BlogPage as being BlogIndexPages
    parent_page_types = ['BlogIndexPage']

    # Specifies what content types can exist as children of BlogPage.
    # Empty list means that no child content types are allowed.
    subpage_types = []


    # promote_panels = [
    #     MultiFieldPanel(Page.promote_panels, "Common page configuration"),
    #     ImageChooserPanel('cover'),
    # ]

    def authors(self):
        """
        Returns the BlogPage's related People. Again note that we are using
        the ParentalKey's related_name from the BlogPeopleRelationship model
        to access these objects. This allows us to access the People objects
        with a loop on the template. If we tried to access the blog_person_
        relationship directly we'd print `blog.BlogPeopleRelationship.None`
        """
        authors = [
            n.people for n in self.blog_person_relationship.all()
        ]

        return authors


class BlogPageGalleryImage(Orderable):
    page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')
    image = models.ForeignKey('wagtailimages.Image', on_delete=models.CASCADE, related_name='+')
    caption = models.CharField(blank=True, max_length=250)

    panels = [
        ImageChooserPanel('image'),
        FieldPanel('caption'),
    ]


class BlogTagIndexPage(Page):
    # tags = ClusterTaggableManager(through=BlogPageTag, blank=True)

    # content_panels = Page.content_panels + [
    #     FieldPanel('tags'),
    # ]
    
    def get_context(self, request):

        # Filter by tag
        tag = request.GET.get('tag')
        blogpages = BlogPage.objects.filter(tags__name=tag)

        # Update template context
        context = super().get_context(request)
        context['blogpages'] = blogpages
        print(context)
        print('get_context，这里有执行吗？')
        return context

    # parent_page_types = ['BlogIndexPage']


# Categories
@register_snippet
class BlogCategory(models.Model):
    name = models.CharField(max_length=255)
    icon = models.ForeignKey(
        'wagtailimages.Image', null=True, blank=True,
        on_delete=models.SET_NULL, related_name='+'
    )

    panels = [
        FieldPanel('name'),
        ImageChooserPanel('icon'),
    ]

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = '内容分类'


@register_snippet       #测试，后台会多出一个片段的模块，添加一个advert入口
class Advert(models.Model):
    url = models.URLField(null=True, blank=True)
    text = models.CharField(max_length=255)

    panels = [
        FieldPanel('url'),
        FieldPanel('text'),
    ]

    def __str__(self):
        return self.text

    class Meta:
        verbose_name_plural = '厉害了'


@register_snippet   # 作者
class People(index.Indexed, ClusterableModel):
    """
    A Django model to store People objects.
    It uses the `@register_snippet` decorator to allow it to be accessible
    via the Snippets UI (e.g. /admin/snippets/base/people/)

    `People` uses the `ClusterableModel`, which allows the relationship with
    another model to be stored locally to the 'parent' model (e.g. a PageModel)
    until the parent is explicitly saved. This allows the editor to use the
    'Preview' button, to preview the content, without saving the relationships
    to the database.
    https://github.com/wagtail/django-modelcluster
    """
    first_name = models.CharField("First name", max_length=254)
    last_name = models.CharField("Last name", max_length=254)
    job_title = models.CharField("Job title", max_length=254)

    image = models.ForeignKey(
        'wagtailimages.Image',
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+'
    )

    panels = [
        MultiFieldPanel([
            FieldRowPanel([
                FieldPanel('first_name', classname="col6"),
                FieldPanel('last_name', classname="col6"),
            ])
        ], "Name"),
        FieldPanel('job_title'),
        ImageChooserPanel('image')
    ]

    search_fields = [
        index.SearchField('first_name'),
        index.SearchField('last_name'),
    ]

    @property
    def thumb_image(self):
        # Returns an empty string if there is no profile pic or the rendition
        # file can't be found.
        try:
            return self.image.get_rendition('fill-50x50').img_tag()
        except:  # noqa: E722 FIXME: remove bare 'except:'
            return ''

    def __str__(self):
        return '{} {}'.format(self.first_name, self.last_name)

    class Meta:
        verbose_name = 'Person'
        verbose_name_plural = 'People'
        

class BlogPeopleRelationship(Orderable, models.Model):
    """
    This defines the relationship between the `People` within the `base`
    app and the BlogPage below. This allows People to be added to a BlogPage.

    We have created a two way relationship between BlogPage and People using
    the ParentalKey and ForeignKey
    """
    page = ParentalKey(
        'BlogPage', related_name='blog_person_relationship', on_delete=models.CASCADE
    )
    people = models.ForeignKey(
        'People', related_name='person_blog_relationship', on_delete=models.CASCADE
    )
    panels = [
        SnippetChooserPanel('people')
    ]